﻿//Copyright Notice:  ©2009 Microsoft Corporation.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

[assembly: CLSCompliant(true)]

namespace Microsoft.InformationSecurity.CISF.Security.AuthZServices
{
    /// <summary>
    /// Represents an Active Directory entry and contains collections of directory entry properties.
    /// </summary>
    public abstract class Entry : Collection<Property>
    {
        #region Private Variables
        protected string entryName;
        //Holds a reference to requested behaviors (strategy pattern).
        private IGetProperty getPropertiesBehavior;

        #endregion

        #region Methods

        #region Add
        /// <summary>
        /// Adds the provided Propery object to the Property collection.
        /// </summary>
        /// <param name="property">A Property object.</param>
        /// <param name="noDuplicates">
        /// true - duplicate property object will be added. 
        /// false - duplicate property objects will be ignored.
        /// </param>
        public void Add(Property property, bool noDuplicates)
        {
            if ((!this.Contains(property)) || !noDuplicates)
                this.Add(property);
        }

        /// <summary>
        /// Adds the property value to the first property of this type found in this entry.
        /// </summary>
        /// <param name="propertye">A Property object.</param>
        /// <param name="propertyType">Type of property.</param>
        /// <param name="propertyValue">The value to add to the Property object.</param>
        /// <param name="noDuplicates">
        /// true - duplicate values will be added. 
        /// false - duplicates will be ignored.
        /// </param>
        public void Add(Property property, AuthZGlobals.PropertyType propertyType, string propertyValue, bool noDuplicates)
        {
            Collection<Property> properties = this.GetProperty(propertyType);
            //If a Property of this type doesn't already exist.
            if (properties.Count == 0)
            {
                property.Add(propertyValue);
                this.Add(property);
            }
            else
                if (!properties[0].Contains(propertyValue) || !noDuplicates)
                    properties[0].Add(propertyValue);
        }


        #endregion

        #region Clear
        /// <summary>
        /// Clears the entry name and removes all Property objects.
        /// </summary>
        public new void Clear()
        {
            this.entryName = "";
            foreach (Property property in this)
                this.Remove(property);
        }

        #endregion

        #region Contains
        /// <summary>
        /// 
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        public new bool Contains(Property property)
        {
            bool contains = false;

            foreach (Property thisProperty in this.GetProperty(property.Type))
            {
                bool match = true;
                for (int i = 0; i < thisProperty.Count; ++i)
                    if (thisProperty[0] != property[0])
                    {
                        match = false;
                        break;
                    }
                if (match)
                {
                    contains = true;
                    break;
                }
            }
            return contains;
        }

        #endregion

        #region GetProperty
        /// <summary>
        /// Gets the Property collection for the type specified.
        /// </summary>
        /// <param name="propertyType">Type of property.</param>
        /// <returns>A collectino of Property objects.</returns>
        public Collection<Property> GetProperty(AuthZGlobals.PropertyType propertyType)
        {
            Collection<Property> retProperty = new Collection<Property>();

            foreach (Property property in this)
                if (property.Type == propertyType)
                    retProperty.Add(property);

            return retProperty;
        }

        #endregion

        #region Load
        /// <summary>
        /// Clears the entry and set this entry equal to the provided Entry object.
        /// </summary>
        /// <param name="entry"></param>
        public void Load(Entry entry)
        {
            this.Clear();
            this.entryName = entry.entryName;
            foreach (Property property in entry)
                this.Add(property);
        }

        #endregion

        #region PerformGetProperties
        /// <summary>
        /// Implements the action to get the property objects for the Entry.
        /// </summary>
        /// <param name="commonNames">Collection of common names to search in AD.</param>
        /// <remarks>Strategy Pattern.</remarks>
        public virtual void PerformGetProperties(Entry entry)
        {
            getPropertiesBehavior.GetProperties(entry);
        }

        #endregion

        #endregion

        #region Properties

        #region Name
        /// <summary>
        /// Gets the entry name.
        /// </summary>
        public string Name
        {
            get { return this.entryName; }
        }

        #endregion

        #region GetPropertiesBehavior
        /// <summary>
        /// Gets or sets the object to use for retrieving the collection of AD properties.
        /// </summary>
        public IGetProperty GetPropertiesBehavior
        {
            get { return getPropertiesBehavior; }
            set { getPropertiesBehavior = value; }
        }

        #endregion

        #endregion

    }
}
